#ifndef SOLVERFACTORY_H
#define SOLVERFACTORY_H

#include "EF_Solver1D_TDMA.h"
#include "EF_Solver1D_TDMA_imp.h"
#include "EF_Solver1D_GeneralThomas.h"
#include "EF_Solver2D_SLU.h"
#include "EF_Solver2D_SLU_DIST.h"
#include "EF_Solver3D_SLU.h"
#include "EF_Solver3D_SLU_DIST.h"
#include "EF_Solver3D_PETSc_KSP.h"
#include "EF_Solver3D_UMFPACK.h"
#include "../Input/PicParams.h"


#include "../Tool/Macros.h"

class SolverFactory {
public:
    static Solver* create(PicParams* params_, ParallelMPI* pmpi_, Grid* grid_, PhysicalField* fields_, Diagnostic* diag_) {
        Solver* solver = NULL;
        int nx_source_left;
        if ( params_->geometry == "1d3v" )
        {
            nx_source_left = 0.0; //default
            if(params_->method == "explicit")
            {
                if(params_->solver_type == "GeneralThomas")
                {
                  solver = new EF_Solver1D_GeneralThomas(params_, pmpi_, grid_, fields_, diag_);
                  log_info<<"GeneralThomas solver is used";
                }
                else if(params_->solver_type == "TDMA")
                {
                  solver = new EF_Solver1D_TDMA(params_, pmpi_, grid_, fields_, diag_);
                  log_info<<"TDMA solver is used";
                }

            }
            else if(params_->method == "implicit")
            {
                solver = new EF_Solver1D_TDMA_imp(params_, pmpi_, grid_, fields_, diag_);
            }

        }
        else if ( params_->geometry == "2d3v" )
        {
            if(params_->solver_type == "SuperLU_serial")
            {
                #ifdef SuperLU_serial
                solver = new EF_Solver2D_SLU(params_, pmpi_, grid_, fields_, diag_);
                #endif
            }
            
            if(params_->solver_type == "SuperLU_mpi")
            {
                #ifdef SuperLU_mpi
                solver = new EF_Solver2D_SLU_DIST(params_, pmpi_, grid_, fields_, diag_);
                #endif
            }    
        }
        else if ( params_->geometry == "3d3v" )
        {
            if(params_->solver_type == "SuperLU_serial")
            {
                #ifdef SuperLU_serial
                solver = new EF_Solver3D_SLU(params_, pmpi_, grid_, fields_, diag_);
                #endif
            }
            
            if(params_->solver_type == "SuperLU_mpi")
            {
                #ifdef SuperLU_mpi
                solver = new EF_Solver3D_SLU_DIST(params_, pmpi_, grid_, fields_, diag_);
                #endif
            } 
            if(params_->solver_type == "petsc")
            {
                #ifdef petsc
                solver = new EF_Solver3D_PETSc_KSP(params_, pmpi_, grid_, fields_, diag_);
                #endif
            }
            if(params_->solver_type == "umfpack")
            {
                #ifdef umfpack
                solver = new EF_Solver3D_UMFPACK(params_, pmpi_, grid_, fields_, diag_);
                #endif
            }
        }
        else 
        {
        }

        if(solver == NULL)
        {
            log_error<<"Creating solver failed, solver_type is: "<<params_->solver_type;
        }

        return solver;
    }

};


#endif
